/* $Header: pi_det.c,v 2.3 03/06/04 11:31:01 przybyls Exp $ */

/***********************************************************************/
/*                                                                     */
/*                  Copyright Hewlett-Packard Co. 1991                 */
/*                                                                     */
/***********************************************************************/

/***********************************************************************/
/* MODULE NAME:                                                        */
/* ============                                                        */
/*                                                                     */
/* Author:                                                             */
/*                                                                     */
/* MODULE PURPOSE:                                                     */
/*                                                                     */
/*                                                                     */
/*                                                                     */
/*                                                                     */
/***********************************************************************/


/*****************************/
/*   GLOBAL INCLUDE FILES    */
/*****************************/

#include <typedefs.h>
#include <error.h>
#include <p_wkfile.h>
#include <wkfile.h>
#include <i_op.h>
#include <p_status.h>
#include <pcb_defs.h>
#include <list_mgmt.h>
#include <detector.h>
#include <math.h>
#include <exception.h>   /* to use Set/Clear Exception */
#include <err_handler.h> /* to use Set/Clear Exception */
#include <glp.h>
#include <clock_ui.h>
#include <keyboard.h>
#include <iomap.h>

/*****************************/
/*   LOCAL INCLUDE FILES     */
/*****************************/

#include "proto.h"

/*****************************/
/*   GLOBAL VARIABLES        */
/*****************************/


/*****************************/
/*   EXTERNAL VARIABLES      */
/*****************************/


/*****************************/
/*   LOCAL DEFINES           */
/*****************************/

/**begin_proto**/

#define  FID_FUEL_GAS 1
#define  FID_AIR_GAS  2
#define  FID_MUG_GAS  3

#define  FPD_FUEL_GAS 1
#define  FPD_AIR_GAS  2
#define  FPD_MUG_GAS  3

#define  NPD_FUEL_GAS 1
#define  NPD_AIR_GAS  2
#define  NPD_MUG_GAS  3

#define  TCD_REF_GAS  2
#define  TCD_MUG_GAS  3

#define  ECD_ANODE_PURGE_GAS 2
#define  ECD_MUG_GAS  3

#define  CalPres Flow

/**end_proto**/

/*****************************/
/*   STATIC VARIABLES        */
/*****************************/


/*****************************/
/*   IMPLEMENT SECTION       */
/*****************************/
/**begin_proto**/
#pragma SECTION PROG=rom3
/**end_proto**/

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

BIT8 DetHasColumn( pDETECTOR_STATUS status )

/**end_proto**/
{

    return status->Has_Column;

}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/* CALLS:                                                              */
/*                                                                     */
/* LIMITATIONS:                                                        */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

INT32 GetDetectorPresActual( pDETECTOR_STATUS  status, INT8  gas )

/**end_proto**/
{
    switch (gas)
    {
        case 1: return ConvertPresIuToDisplay ( status->Gas_1.Current_Pres, status->Gas_1.Dcm2_Per_IU );
        case 2: return ConvertPresIuToDisplay ( status->Gas_2.Current_Pres, status->Gas_2.Dcm2_Per_IU );
        case 3: return ConvertPresIuToDisplay ( status->Gas_3.Current_Pres, status->Gas_3.Dcm2_Per_IU );
        default: return 0; /* only to keep lint happy */
    }
}

/**begin_proto**/

INT32 DcGetDetectorPresActual( pDETECTOR_STATUS  status, INT8  gas )

/**end_proto**/
{
    if ( 0 != GetMaxDetGasFlow( status, gas ) )
    {
        return 0;  /* b/c det gas channel is in flow  mode ; i.e. no frit */
    };

    switch (gas)
    {
        case 1: return ConvertPresIuToDcu ( status->Gas_1.Current_Pres, status->Gas_1.Dcm2_Per_IU );
        case 2: return ConvertPresIuToDcu ( status->Gas_2.Current_Pres, status->Gas_2.Dcm2_Per_IU );
        case 3: return ConvertPresIuToDcu ( status->Gas_3.Current_Pres, status->Gas_3.Dcm2_Per_IU );
        default: return 0; /* only to keep lint happy */
    }
}


/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/* CALLS:                                                              */
/*                                                                     */
/* LIMITATIONS:                                                        */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

INT32 GetDetectorGasFlowActual( pDETECTOR_STATUS  status, INT8  gas )

/**end_proto**/
{
    switch ( gas )
    {
        case 1: if (( status->Ready.Fuel_Pres.State == IN_CONTROL_ ) || ( status->Ready.Fuel_Pres.State == NOT_READY_DELAY))
                {
                   return ConvertFlowIuToDisplay ( status->Gas_1.Desired_Flow, status->IU_Scaling );
                }
                else
                {
                   return ConvertFlowIuToDisplay ( status->Gas_1.Filtered_Current_Flow, status->IU_Scaling );
                }
        case 2: if (( status->Ready.Util_Pres.State == IN_CONTROL_ ) || ( status->Ready.Util_Pres.State == NOT_READY_DELAY))
                {
                   return ConvertFlowIuToDisplay ( status->Gas_2.Desired_Flow, status->IU_Scaling );
                }
                else
                {
                   return ConvertFlowIuToDisplay ( status->Gas_2.Filtered_Current_Flow, status->IU_Scaling );
                }
        case 3: if (( status->Ready.Mug_Pres.State == IN_CONTROL_ ) || ( status->Ready.Mug_Pres.State == NOT_READY_DELAY ))
                {
                   return ConvertFlowIuToDisplay ( status->Gas_3.Desired_Flow, status->IU_Scaling );
                }
                else
                {
                   return ConvertFlowIuToDisplay ( status->Gas_3.Filtered_Current_Flow, status->IU_Scaling );
                }
        default: return 0; /* only to keep lint happy */
    }
}
/**begin_proto**/

INT32 DcGetDetectorGasFlowActual( pDETECTOR_STATUS  status, INT8  gas )

/**end_proto**/
{
    if ( 0 == GetMaxDetGasFlow( status, gas ) )
    {
        return 0;  /* b/c det gas channel is in pressure mode ; i.e. no frit */
    };

    switch ( gas )
    {
        case 1: return ConvertFlowIuToDcu ( status->Gas_1.Filtered_Current_Flow, status->IU_Scaling );
        case 2: return ConvertFlowIuToDcu ( status->Gas_2.Filtered_Current_Flow, status->IU_Scaling );
        case 3: return ConvertFlowIuToDcu ( status->Gas_3.Filtered_Current_Flow, status->IU_Scaling );
        default: return 0; /* only to keep lint happy */
    }
}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/* CALLS:                                                              */
/*                                                                     */
/* LIMITATIONS:                                                        */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

INT32 GetDetGasWkfileFlowSetpt( pDETECTOR_STATUS  status, INT8  gas )

/**end_proto**/
{
    switch ( gas )
    {
        case 1: return ConvertFlowIuToDisplay ( status->Wkfile->Gas_1.Desired_Flow, status->IU_Scaling );
        case 2: return ConvertFlowIuToDisplay ( status->Wkfile->Gas_2.Desired_Flow, status->IU_Scaling );
        case 3: return ConvertFlowIuToDisplay ( status->Wkfile->Gas_3.Desired_Flow, status->IU_Scaling );
        default: return 0; /* only to keep lint happy */
    }
}
/**begin_proto**/

INT32 DcGetDetGasWkfileFlowSetpt( pDETECTOR_STATUS  status, INT8  gas )

/**end_proto**/
{
    switch ( gas )
    {
        case 1: return ConvertFlowIuToDcu ( status->Wkfile->Gas_1.Desired_Flow, status->IU_Scaling );
        case 2: return ConvertFlowIuToDcu ( status->Wkfile->Gas_2.Desired_Flow, status->IU_Scaling );
        case 3: return ConvertFlowIuToDcu ( status->Wkfile->Gas_3.Desired_Flow, status->IU_Scaling );
        default: return 0; /* only to keep lint happy */
    }
}

/**begin_proto**/

INT32 GetDetectorGasFlowSetpt( pDETECTOR_STATUS  status, INT8  gas )

/**end_proto**/
{
    switch ( gas )
    {
        case 1: return ConvertFlowIuToDisplay ( status->Gas_1.Desired_Flow, status->IU_Scaling );
        case 2: return ConvertFlowIuToDisplay ( status->Gas_2.Desired_Flow, status->IU_Scaling );
        case 3: return ConvertFlowIuToDisplay ( status->Gas_3.Desired_Flow, status->IU_Scaling );
        default: return 0; /* only to keep lint happy */
    }
}
/**begin_proto**/

INT32 DcGetDetectorGasFlowSetpt( pDETECTOR_STATUS  status, INT8  gas )

/**end_proto**/
{
    if ( 0 == GetMaxDetGasFlow( status, gas ) )
    {
        return 0;  /* b/c det gas channel is in pressure mode ; i.e. no frit */
    };

    switch ( gas )
    {
        case 1: return ConvertFlowIuToDcu ( status->Gas_1.Desired_Flow, status->IU_Scaling );
        case 2: return ConvertFlowIuToDcu ( status->Gas_2.Desired_Flow, status->IU_Scaling );
        case 3: return ConvertFlowIuToDcu ( status->Gas_3.Desired_Flow, status->IU_Scaling );
        default: return 0; /* only to keep lint happy */
    }
}



/**begin_proto**/
INT32 GetDetectorGasPresSetpt( pDETECTOR_STATUS  status, INT8  gas )
/**end_proto**/
{
    switch ( gas )
    {
        case 1: return ConvertPresIuToDisplay ( status->Gas_1.Desired_Pres,   status->Gas_1.Dcm2_Per_IU );
        case 2: return ConvertPresIuToDisplay ( status->Gas_2.Desired_Pres,   status->Gas_2.Dcm2_Per_IU );
        case 3: return ConvertPresIuToDisplay ( status->Gas_3.Desired_Pres,   status->Gas_3.Dcm2_Per_IU );
        default: return 0; /* only to keep lint happy */
    }
}

/**begin_proto**/
INT32 DcGetDetectorGasPresSetpt( pDETECTOR_STATUS  status, INT8  gas )
/**end_proto**/
{
    if ( 0 != GetMaxDetGasFlow( status, gas ) )
    {
        return 0;  /* b/c det gas channel is in flow  mode ; i.e. no frit */
    };

    switch ( gas )
    {
        case 1: return ConvertPresIuToDcu     ( status->Gas_1.Desired_Pres,   status->Gas_1.Dcm2_Per_IU );
        case 2: return ConvertPresIuToDcu     ( status->Gas_2.Desired_Pres,   status->Gas_2.Dcm2_Per_IU );
        case 3: return ConvertPresIuToDcu     ( status->Gas_3.Desired_Pres,   status->Gas_3.Dcm2_Per_IU );
        default: return 0; /* only to keep lint happy */
    }
}

/**begin_proto**/

void ChangeDetPresSetpt( U_INT16 pres, INT32 setpt, pDETECTOR_STATUS status, BIT8 gas )

/**end_proto**/
{
    switch ( gas )
    {
       case 1:
          status->Gas_1.Desired_Pres = pres ;
          status->Wkfile->Gas_1.Desired_Pres = pres ;
          LogSetptChange( status->Position == FRNT_DET ? F_DET_GAS1_PRES : B_DET_GAS1_PRES, setpt, (INT32)GetPresUnits() );
          status->Ready.Pres1_Setpt_Change = TRUE;
                   break;

       case 2:
          status->Gas_2.Desired_Pres = pres ;
          status->Wkfile->Gas_2.Desired_Pres = pres ;
          LogSetptChange( status->Position == FRNT_DET ? F_DET_GAS2_PRES : B_DET_GAS2_PRES, setpt, (INT32)GetPresUnits() );
          status->Ready.Pres2_Setpt_Change = TRUE;
                   break;

       case 3:
          status->Gas_3.Desired_Pres = pres ;
          status->Wkfile->Gas_3.Desired_Pres = pres ;
          LogSetptChange( status->Position == FRNT_DET ? F_DET_GAS3_PRES : B_DET_GAS3_PRES, setpt, (INT32)GetPresUnits() );
          status->Ready.Pres3_Setpt_Change = TRUE;
                   break;
    }

}


/**begin_proto**/
UI_ERR ValidateDetPresSetpt ( INT32 setpt, pDETECTOR_STATUS  status, BIT8  gas )
/**end_proto**/
{
    if (( gas < 1 ) || ( gas > 3 )) return INVALID_PARAM;

    if ( !EpcDetector( status ) )   return NOT_INSTALLED;

    if ( setpt > GetDetPresRange(status , gas  ) ) return PARAM_TOO_LARGE;

    return OK;
}


/**begin_proto**/

UI_ERR SetDetPresSetpt( INT32 setpt, pDETECTOR_STATUS status, BIT8 gas  )

/**end_proto**/
{

    U_INT32  setpt_iu;
    UI_ERR   validate;

    setpt_iu = ConvertPresDisplayToIu(setpt, GetDetPresScale(  status, gas ) ) ;
    validate = ValidateDetPresSetpt( setpt, status ,gas );

    if (validate == OK)
    {
        LockResource( &Inst_Status.Pneu.Resource_Lock );

        ChangeDetPresSetpt( setpt_iu, setpt, status ,gas );

        if (( GetDetGasState ( status,  gas ) != ON ) && ( setpt > 0 ))
        {
              UpdateDetGasState( ON, status , (U_INT8)gas );
        }

        ReleaseResource( &Inst_Status.Pneu.Resource_Lock );
    }

    return validate;
}

/**begin_proto**/

UI_ERR DcSetDetPresSetpt( INT32 setpt, pDETECTOR_STATUS status, BIT8 gas  )

/**end_proto**/
{
    U_INT32  setpt_iu;
    UI_ERR   validate;

    setpt_iu =ConvertPresDcuToIu(setpt, GetDetPresScale(  status, gas ) ) ;
    setpt    = ConvertPresIuToDisplay( setpt_iu, (gas==1) ? status->Gas_1.Dcm2_Per_IU :
                                                 (gas==2) ? status->Gas_2.Dcm2_Per_IU :
                                                            status->Gas_3.Dcm2_Per_IU );

    validate = ValidateDetPresSetpt( setpt, status ,gas );

    if (validate == OK)
    {
        ChangeDetPresSetpt( setpt_iu, setpt, status ,gas );

        if (( GetDetGasState ( status,  gas ) == OFF ) && ( setpt > 0 ))
        {
              UpdateDetGasState( ON, status , (U_INT8)gas );
        }
    }

    return validate;
}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/* CALLS:                                                              */
/*                                                                     */
/* LIMITATIONS:                                                        */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

UI_ERR SetDetectorGasFlowSetpt( INT32 setpt, pDETECTOR_STATUS  status, INT8  gas )

/**end_proto**/
{


    UI_ERR   error;
    U_INT32  flow;

    error = ValidateDetFlowSetpt( setpt, status, gas );

    flow =  ConvertFlowDisplayToIu ( setpt, status->IU_Scaling );

    if ( error == OK )
    {
         LockResource( &Inst_Status.Pneu.Resource_Lock );

         ChangeDetFlowSetpt( setpt, flow, status, gas );

         if ( !DoingMethodInstall() )  /* method will restart with the NZ cmds */
         {
            UpdateDetGasState ( ON, status, gas );
         }

         ReleaseResource( &Inst_Status.Pneu.Resource_Lock );
    }

    return error;

}

/**begin_proto**/

UI_ERR DcSetDetectorGasFlowSetpt( INT32 setpt, pDETECTOR_STATUS  status, INT8  gas )

/**end_proto**/
{

    UI_ERR   error;
    U_INT32  flow;

    flow =  ConvertFlowDcuToIu ( setpt, status->IU_Scaling );

    setpt = ConvertFlowIuToDisplay ( flow, status->IU_Scaling );

    error = ValidateDetFlowSetpt( setpt, status, gas );

    if ( error == OK )
    {
         ChangeDetFlowSetpt( setpt, flow, status, gas );
    }

    return error;

}

/**begin_proto**/
UI_ERR ValidateDetFlowSetpt ( INT32 setpt, pDETECTOR_STATUS  status, INT8  gas )
/**end_proto**/
{
    if (( gas < 1 ) || ( gas > 3 )) return INVALID_PARAM;

    if ( !EpcDetector( status ) )   return NOT_INSTALLED;

    if ( setpt < GetMinDetGasFlow ( status, gas )) return PARAM_TOO_SMALL;
    if ( setpt > GetMaxDetGasFlow ( status, gas )) return PARAM_TOO_LARGE;

    return OK;
}

/**begin_proto**/
void ChangeDetFlowSetpt  ( INT32 setpt, U_INT32 flow, pDETECTOR_STATUS  status, INT8  gas )
/**end_proto**/
{
    U_INT32 combo_flow;

    switch ( gas )
    {
       case 1: status->Gas_1.Desired_Flow = flow;
               status->Wkfile->Gas_1.Desired_Flow = flow;
               LogSetptChange( status->Position == FRNT_DET ? F_DET_FUEL_FLOW : B_DET_FUEL_FLOW, setpt, 0 );
               status->Ready.Fuel_Setpt_Change = TRUE;
               break;

       case 2: status->Gas_2.Desired_Flow = flow;
               status->Wkfile->Gas_2.Desired_Flow = flow;
               LogSetptChange( status->Position == FRNT_DET ? F_DET_UTIL_FLOW : B_DET_UTIL_FLOW,
                               setpt, (INT32)status->Config->Type );
               status->Ready.Util_Setpt_Change = TRUE;
               break;

       case 3: if ( status->Wkfile->Constant_Total_Makeup == ON )
               {
                   combo_flow = flow + FindTotalOutletFlow ( status->Position, status->IU_Scaling );
                   flow = ConvertFlowIuToDisplay( combo_flow, status->IU_Scaling );
                   (void) ChangeConstMakeupFlowSetpt( combo_flow, flow, status );
               }
               else
               {
                   status->Gas_3.Desired_Flow = flow;
                   status->Wkfile->Gas_3.Desired_Flow = flow;
                   LogSetptChange( status->Position == FRNT_DET ? F_DET_MUG_FLOW : B_DET_MUG_FLOW,
                                   setpt, (INT32)status->Config->Type );
               }
               status->Ready.Mug_Setpt_Change = TRUE;
               break;
    }


}

/**begin_proto**/
void PutDetAirSetptImmed( INT32 setpt, pDETECTOR_STATUS  status ) /* setpt in units of 0.1 ml/min */
/**end_proto**/
{
    status->Gas_2.Desired_Flow = ConvertFlowDisplayToIu ( setpt, status->IU_Scaling );
    UpdateDetGasState ( ON, status, 2 );
}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

ON_OFF GetDetGasState ( pDETECTOR_STATUS status, U_INT8 gas )

/**end_proto**/
{
     switch ( gas )
     {
         case 1:     if ( status->Gas_1.Shutdown ) return SHUTDOWN;
                     else                          return status->Gas_1.On_Off;

         case 2:     if ( status->Gas_2.Shutdown ) return SHUTDOWN;
                     else                          return status->Gas_2.On_Off;

         case 3:     if ( status->Gas_3.Shutdown ) return SHUTDOWN;
                     else                          return status->Gas_3.On_Off;
         default: return OFF; /* only to keep lint happy */
     }

}

/**begin_proto**/

ON_OFF GetDetGasWkfileState ( pDETECTOR_STATUS status, U_INT8 gas )

/**end_proto**/
{
     switch ( gas )
     {
         case 1:     return status->Wkfile->Gas_1.On_Off;
         case 2:     return status->Wkfile->Gas_2.On_Off;
         case 3:     return status->Wkfile->Gas_3.On_Off;
         default: return OFF; /* only to keep lint happy */
     }

}

/**begin_proto**/

UI_ERR SetDetGasState ( ON_OFF state, pDETECTOR_STATUS status, U_INT8 gas )

/**end_proto**/
{
   BIT8 setpt_changed;

     setpt_changed = ( GetDetGasState( status, gas ) != state );

     switch ( gas )
     {
        case 1: UpdateDetGasState( state, status, gas );
                if ( setpt_changed )
                {
                   if ( state == ON )
                   {
                     LogSetptChange( status->Position == FRNT_DET ? F_DET_FUEL_ON : B_DET_FUEL_ON, 0, (INT32)status->Config->Type );
                   }
                   else
                   {
                      LogSetptChange( status->Position == FRNT_DET ? F_DET_FUEL_OFF : B_DET_FUEL_OFF, 0, (INT32)status->Config->Type );
                   }
                }
                break;
        case 2: UpdateDetGasState( state, status, gas );
                if ( setpt_changed )
                {
                   if ( state == ON )
                   {
                     LogSetptChange( status->Position == FRNT_DET ? F_DET_UTIL_ON : B_DET_UTIL_ON, 0, (INT32)status->Config->Type );
                   }
                   else
                   {
                      LogSetptChange( status->Position == FRNT_DET ? F_DET_UTIL_OFF : B_DET_UTIL_OFF, 0, (INT32)status->Config->Type );
                   }
                }
                break;
        case 3: UpdateDetGasState( state, status, gas );
                if ( setpt_changed )
                {
                   if ( state == ON )
                   {
                     LogSetptChange( status->Position == FRNT_DET ? F_DET_MUG_ON : B_DET_MUG_ON, 0, (INT32)status->Config->Type );
                   }
                   else
                   {
                      LogSetptChange( status->Position == FRNT_DET ? F_DET_MUG_OFF : B_DET_MUG_OFF, 0, (INT32)status->Config->Type );
                   }
                }
                break;
     }

     return OK;
}

/**begin_proto**/

#pragma SECTION UNDO

void UpdateDetGasState ( ON_OFF state, pDETECTOR_STATUS status, U_INT8 gas )

/**end_proto**/
{
   BIT8 old_shutdown_state;

   old_shutdown_state = status->Shutdown;

     switch ( gas )
     {
        case 1:     if (( state == ON ) || ( state == OFF ))
                    {
                        status->Wkfile->Gas_1.On_Off = state;
                        status->Gas_1.On_Off         = state;

                        if ( state == OFF )
                        {
                            status->Gas_1.Filtered_Flow_Setpt   = 0;
                        }

                        if ( status->Gas_1.Shutdown )
                        {
                            status->Gas_1.Shutdown = FALSE;
                        }

                    }

                    if (status->Gas_1.FRIT_MAX_FLOW  != 0 )
                       { status->Ready.Fuel_Setpt_Change = TRUE; }
                    else
                       { status->Ready.Pres1_Setpt_Change = TRUE;}

                    break;

        case 2:     if (( state == ON ) || ( state == OFF ))
                    {
                        if (( state == OFF )&& ( (DET_TYPE)( (INT16)status->Config->Type & 0xf ) == TCD ))
                            {
                              TCDOff( status->Position == FRNT_DET ? FRONT : BACK );
                            };

                        status->Wkfile->Gas_2.On_Off = state;
                        status->Gas_2.On_Off         = state;


                        if ( state == OFF )
                        {
                            status->Gas_2.Filtered_Flow_Setpt   = 0;
                        }

                        if ( status->Gas_2.Shutdown )
                        {
                            status->Gas_2.Shutdown = FALSE;
                        }

                    }

                    if (status->Gas_2.FRIT_MAX_FLOW != 0 )
                       { status->Ready.Util_Setpt_Change = TRUE; }
                    else
                       { status->Ready.Pres2_Setpt_Change = TRUE;}

                    break;

        case 3:     if (( state == ON ) || ( state == OFF ))
                    {
                        status->Wkfile->Gas_3.On_Off = state;
                        status->Gas_3.On_Off         = state;

                        if ( state == OFF )
                        {
                            status->Gas_3.Filtered_Flow_Setpt   = 0;
                        }

                        if ( status->Gas_3.Shutdown )
                        {
                            status->Gas_3.Shutdown = FALSE;
                        }

                    }

                    if (status->Gas_3.FRIT_MAX_FLOW != 0 )
                       { status->Ready.Mug_Setpt_Change = TRUE; }
                    else
                       { status->Ready.Pres3_Setpt_Change = TRUE;}

                    break;

     }

     if (( status->Gas_1.Shutdown == FALSE ) &&
         ( status->Gas_2.Shutdown == FALSE ) &&
         ( status->Gas_3.Shutdown == FALSE ))    status->Shutdown = FALSE;

     if ( old_shutdown_state && !status->Shutdown )
     {
        /* we were shutdown and now we are not, restart ALL det channels */

        if ( status->Position == FRNT_DET )
        {
            ClearNewException( FRNT_DET_GAS_1_SHUTDOWN );
            ClearNewException( FRNT_DET_GAS_2_SHUTDOWN );
            ClearNewException( FRNT_DET_GAS_3_SHUTDOWN );

            if ( EpcDetector( status ) )
            {
                 QuickRestartChannel( FRNT_DETECTOR_GAS_1_MASK |
                                      FRNT_DETECTOR_GAS_2_MASK |
                                      FRNT_DETECTOR_GAS_3_MASK, 3 );
            }
        }
        else
        {
            ClearNewException( BACK_DET_GAS_1_SHUTDOWN );
            ClearNewException( BACK_DET_GAS_2_SHUTDOWN );
            ClearNewException( BACK_DET_GAS_3_SHUTDOWN );

            if ( EpcDetector( status ) )
            {
                 QuickRestartChannel( BACK_DETECTOR_GAS_1_MASK |
                                      BACK_DETECTOR_GAS_2_MASK |
                                      BACK_DETECTOR_GAS_3_MASK, 3 );
            }
        }
     }
}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

#pragma SECTION PROG=rom3

ON_OFF GetDetConstMkupMode ( pDETECTOR_STATUS status )

/**end_proto**/
{

     return status->Wkfile->Constant_Total_Makeup;

}

/**begin_proto**/

UI_ERR SetDetConstMkupMode (ON_OFF state, pDETECTOR_STATUS status )

/**end_proto**/
{
     status->Ready.Mug_Setpt_Change = TRUE;

     if ( state == OFF )
     {
           status->Wkfile->Constant_Total_Makeup = state;
           LogSetptChange( status->Position == FRNT_DET ? F_DET_NORMAL_MUG_MODE : B_DET_NORMAL_MUG_MODE, 0, 0 );
           return OK;
     }

     if (( state == ON ) && ( status->Has_Column == TRUE ))
     {
           status->Wkfile->Constant_Total_Makeup = state;
           LogSetptChange( status->Position == FRNT_DET ? F_DET_CONST_COL_MUG_MODE : B_DET_CONST_COL_MUG_MODE, 0, 0 );
           if ( status->Wkfile->Desired_Total_Makeup_Flow == 0 )
           {
                status->Wkfile->Desired_Total_Makeup_Flow = status->Wkfile->Gas_3.Desired_Flow;
           }
           return OK;
     }
     return INVALID_PARAM;
}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

INT32 GetConstMakeupFlowSetpt ( pDETECTOR_STATUS status )

/**end_proto**/
{

      return ConvertFlowIuToDisplay ( status->Wkfile->Desired_Total_Makeup_Flow, status->IU_Scaling );
}

/**begin_proto**/

INT32 GetMaxComboFlow ( pDETECTOR_STATUS status )

/**end_proto**/
{
      return GetMaxDetGasFlow ( status, 3 );
}

/**begin_proto**/

INT32 DcGetConstMakeupFlowSetpt ( pDETECTOR_STATUS status )

/**end_proto**/
{

      return ConvertFlowIuToDcu ( status->Wkfile->Desired_Total_Makeup_Flow, status->IU_Scaling );
}

/**begin_proto**/

UI_ERR SetConstMakeupFlowSetpt ( INT32 flow, pDETECTOR_STATUS status )

/**end_proto**/
{

    U_INT32  flow_iu;
    UI_ERR   error;

    if ( (error = ValidateDetFlowSetpt ( flow, status, 3 )) != OK ) return error;

    flow_iu = ConvertFlowDisplayToIu(flow, status->IU_Scaling );

    return ChangeConstMakeupFlowSetpt( flow_iu, flow, status );
}

/**begin_proto**/

UI_ERR DcSetConstMakeupFlowSetpt ( INT32 flow, pDETECTOR_STATUS status )

/**end_proto**/
{

    U_INT32  flow_iu;
    INT32    flow_du;
    UI_ERR   error;

    flow_iu = ConvertFlowDcuToIu(flow, status->IU_Scaling );
    flow_du = ConvertFlowIuToDisplay(flow_iu, status->IU_Scaling );

    if ( (error = ValidateDetFlowSetpt ( flow_du, status, 3 )) != OK ) return error;

    return ChangeConstMakeupFlowSetpt( flow_iu, flow_du, status );

}

/**begin_proto**/

UI_ERR ChangeConstMakeupFlowSetpt ( U_INT32 flow_iu, INT32 flow, pDETECTOR_STATUS status )

/**end_proto**/
{

    U_INT32  column_flow;

    column_flow = FindTotalOutletFlow ( status->Position, status->IU_Scaling );

#if 0

 this causes errors with workfile download

    if ( flow_iu < column_flow ) return NOT_ALLOWED;

#endif

    status->Wkfile->Desired_Total_Makeup_Flow = flow_iu;
    status->Wkfile->Gas_3.Desired_Flow = flow_iu - column_flow;
    status->Gas_3.Desired_Flow = flow_iu - column_flow;

    LogSetptChange( status->Position == FRNT_DET ? F_DET_COMBO_FLOW : B_DET_COMBO_FLOW, flow, 0 );

    status->Ready.Mug_Setpt_Change = TRUE;

    return OK;
}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/


#define NO INVALID_PARAM
#define NUM_GAS 8
#define NUM_DET 7

const U_INT16 Valid_Det_Gas_Types[NUM_GAS][NUM_DET][3] = {

       /*       FID           TCD           ECD           NPD           FPD          uECD           HID       */
       /*                                                                            uECD2                    */
       /*        O                           P             O             O                                    */
       /*     F  x                           u          F  x          F  x                                    */
       /*     u  d  M          R  M          r  M       u  d  M       u  d  M             M             M     */
       /*     e  z  U          e  U          g  U       e  z  U       e  z  U             U             U     */
       /*     l  r  G          f  G          e  G       l  r  G       l  r  G             G             G     */
       /*                                                                                                     */
/* N2 */  { { 0, 0, 1 },  { 0, 1, 1 },  { 0, 1, 1 },  { 0, 0, 1 },  { 0, 0, 1 },  { 0, 0, 1 },  { 0, 0, 0 }  },
/* H2 */  { { 1, 0, 0 },  { 0, 1, 1 },  { 0, 0, 0 },  { 1, 0, 0 },  { 1, 0, 0 },  { 0, 0, 0 },  { 0, 0, 0 }  },
/* He */  { { 0, 0, 1 },  { 0, 1, 1 },  { 0, 0, 0 },  { 0, 0, 1 },  { 0, 0, 1 },  { 0, 0, 0 },  { 0, 0, 1 }  },
/* ArMe */{ { 0, 0, 0 },  { 0, 0, 0 },  { 0, 1, 1 },  { 0, 0, 0 },  { 0, 0, 0 },  { 0, 0, 1 },  { 0, 0, 0 }  },
/* O2 */  { { 0, 0, 0 },  { 0, 0, 0 },  { 0, 0, 0 },  { 0, 0, 0 },  { 0, 0, 0 },  { 0, 0, 0 },  { 0, 0, 0 }  },
/* Air */ { { 0, 1, 0 },  { 0, 0, 0 },  { 0, 0, 0 },  { 0, 1, 0 },  { 0, 1, 0 },  { 0, 0, 0 },  { 0, 0, 0 }  },
/* Ar */  { { 0, 0, 0 },  { 0, 0, 0 },  { 0, 0, 0 },  { 0, 0, 0 },  { 0, 0, 0 },  { 0, 0, 0 },  { 0, 0, 0 }  },
/* ?? */  { { 0, 0, 0 },  { 0, 0, 0 },  { 0, 0, 0 },  { 0, 0, 0 },  { 0, 0, 0 },  { 0, 1, 0 },  { 0, 1, 0 }  } };


/**begin_proto**/

BIT8   DetIsTCDorAnyECD ( pDETECTOR_STATUS status )

/**end_proto**/
{
   return (( status->Config->Type == EPC_TCD )  || ( status->Config->Type == EPC_ECD ) ||
           ( status->Config->Type == EPC_uECD ) || ( status->Config->Type == EPC_uECD2    )) ;
}

/**begin_proto**/

BIT8   DetIsAnyUECD   ( pDETECTOR_STATUS status )

/**end_proto**/
{
   return (( status->Config->Type == EPC_uECD ) || ( status->Config->Type == EPC_uECD2 )) ;
}

BIT8   DetIsAnyUECDorLDID   ( pDETECTOR_STATUS status )

{
   return (( status->Config->Type == EPC_uECD ) || ( status->Config->Type == EPC_uECD2 ) ||
           ( status->Config->Type == EPC_LDID )                                             );
}

/**begin_proto**/

UI_ERR ValidateDetectorGasType ( pDETECTOR_STATUS status, U_INT8 gas, GAS_TYPE gas_type )

/**end_proto**/
{
   DET_TYPE type;

   type = (DET_TYPE)(0x0f & (INT16)status->Config->Type);

/*   The logic done below in the "switch" SHOULD be done in an 1x8 rom-based array:                               */
/*                                                                                                                */
/*      -----------------------------------------                                                                 */
/*      |    |    |    |    |    |    |    |    | where index into 1x8 is type and output is used as              */
/*      | 0  | 1  | 2  | 3  | 4  | x  | 5  | 5  |  the 2nd index "NUM_DET" into the                               */
/*      |    |    |    |    |    |    |    |    |  "Valid_Det_Gas_Types[NUM_GAS][NUM_DET][3]" array .             */
/*      -----------------------------------------  "x" is used to force rtn of INVALID_PARAM for AIB              */
/*                                                                                                                */

   switch (type)
   {
       case FID:
       case TCD:
       case ECD:
       case NPD:
       case FPD: type = (DET_TYPE)((INT16)type - 1);
                 break;

       case NO_DET:
       case AIB: return OK; /* this is to emulate IQ1 code that maps an out-of-bound array reference into a bogus OK */

       case uECD:  type = (DET_TYPE)((INT16)type - 2);
                   break;
       case uECD2: type = (DET_TYPE)((INT16)type - 3);
                   break;

       case LDID:  type = (DET_TYPE)((INT16)type - 4);
                   break;

       case OEM_AIB: return ValidAuxGasType(gas_type) ;

       default: return INVALID_PARAM ;
   }

   return ( Valid_Det_Gas_Types [ (U_INT8)  gas_type ]
                                [ (U_INT16) type     ]
                                [           gas -1   ]
                        == 0 ) ? INVALID_PARAM : OK;
}

/**begin_proto**/

GAS_TYPE GetDetectorGasType ( pDETECTOR_STATUS status, U_INT8 gas )

/**end_proto**/
{
      switch ( gas )
      {
          case 1:  return status->Config->Gas_1.Gas_Type;
          case 2:  return status->Config->Gas_2.Gas_Type;
          case 3:  return status->Config->Gas_3.Gas_Type;
          default: return UNKNOWN_GAS; /* only to keep lint happy */
      }

}

/**begin_proto**/

UI_ERR SetDetectorGasType ( pDETECTOR_STATUS status, U_INT8 gas, GAS_TYPE gas_type )

/**end_proto**/
{

     UI_ERR return_value;
     EEPROM_DET_TYPE type;

     type = status->Config->Type;

     if ( type == (EEPROM_DET_TYPE)NO_DET )
     {
         if ((( status->Position == FRNT_DET ) ? (DISCRETE_IN1 & 0x0f) : ( (DISCRETE_IN1 & 0xf0)>>4)) == (U_INT8)AIB )
         {
             switch ( gas )
             {
                 case 1:  if ( gas_type == status->Config->Gas_1.Gas_Type ) return OK;
                          else                                              return INVALID_PARAM;
                 case 2:  if ( gas_type == status->Config->Gas_2.Gas_Type ) return OK;
                          else                                              return INVALID_PARAM;
                 case 3:  if ( gas_type == status->Config->Gas_3.Gas_Type ) return OK;
                          else                                              return INVALID_PARAM;
                 default: return INVALID_PARAM; /* only to keep lint happy */
             }
         }
     }

     if ( ( return_value = ValidateDetectorGasType ( status, gas, gas_type ) ) == OK )
     {
          SendDetGasChangeRequest( status, gas, gas_type );

          if ( type == EPC_OEM )
          {
             LogSetptChange( status->Position == FRNT_DET ? F_DET_OEM_GAS_TYPE : B_DET_OEM_GAS_TYPE ,
                       gas, (INT32)gas_type  );
          }

          switch ( gas )
          {
               case 1:  status->Ready.Fuel_Setpt_Change = TRUE;
                        break;
               case 2:  status->Ready.Util_Setpt_Change = TRUE;

                        if (( type == EPC_TCD ) || ( type == EPC_ECD ))
                        {
                             status->Ready.Mug_Setpt_Change = TRUE;
                             SendDetGasChangeRequest( status, 3, gas_type );
                        }

                        switch ( type )
                        {
                           case MAN_FPD:
                           case EPC_FPD: LogSetptChange( status->Position == FRNT_DET ? F_DET_FPD_UTIL_TYPE :
                                                                                        B_DET_FPD_UTIL_TYPE,
                                                     0, (INT32)gas_type  );
                                     break;

                           case EPC_TCD: LogSetptChange( status->Position == FRNT_DET ? F_DET_TCD_UTIL_MUG_TYPE :
                                                                                        B_DET_TCD_UTIL_MUG_TYPE,
                                                     0, (INT32)gas_type  );
                                     break;

                           case MAN_TCD: LogSetptChange( status->Position == FRNT_DET ? F_DET_TCD_UTIL_TYPE :
                                                                                        B_DET_TCD_UTIL_TYPE,
                                                     0, (INT32)gas_type  );
                                     break;

                           case EPC_ECD: LogSetptChange( status->Position == FRNT_DET ? F_DET_ECD_UTIL_MUG_TYPE :
                                                                                        B_DET_ECD_UTIL_MUG_TYPE,
                                                     0, (INT32)gas_type  );
                                     break;
                           case MAN_ECD: LogSetptChange( status->Position == FRNT_DET ? F_DET_ECD_UTIL_TYPE :
                                                                                        B_DET_ECD_UTIL_TYPE,
                                                     0, (INT32)gas_type  );
                                     break;
                        }
                        break;
               case 3:  status->Ready.Mug_Setpt_Change = TRUE;

                        if (( type == EPC_TCD ) || ( type == EPC_ECD ))
                        {
                             status->Ready.Util_Setpt_Change = TRUE;
                             SendDetGasChangeRequest( status, 2, gas_type );
                        }
                        switch ( type )
                        {
                           case MAN_FID:
                           case EPC_FID:
                           case MAN_NPD:
                           case EPC_NPD:
                           case MAN_FPD:
                           case EPC_FPD:
                           case MAN_TCD:
                           case EPC_uECD:
                           case EPC_uECD2:
                           case EPC_LDID:
                           case MAN_ECD: LogSetptChange( status->Position == FRNT_DET ? F_DET_MUG_TYPE :
                                                                                        B_DET_MUG_TYPE,
                                                     0, (INT32)gas_type  );
                                     break;

                           case EPC_TCD: LogSetptChange( status->Position == FRNT_DET ? F_DET_TCD_UTIL_MUG_TYPE :
                                                                                        B_DET_TCD_UTIL_MUG_TYPE,
                                                     0, (INT32)gas_type  );
                                     break;

                           case EPC_ECD: LogSetptChange( status->Position == FRNT_DET ? F_DET_ECD_UTIL_MUG_TYPE :
                                                                                        B_DET_ECD_UTIL_MUG_TYPE,
                                                     0, (INT32)gas_type  );
                                     break;
                        }
                        break;
          }
     }

     DetGasTypeChanged( DET_POSITION(status) );

     return return_value;
}

/**begin_proto**/
#pragma SECTION UNDO
/**end_proto**/
/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

void DetGasOFF ( POSITION position , U_INT8 gas )

/**end_proto**/
{

     pDETECTOR_STATUS status;

     if ( position == FRONT ) status = &Inst_Status.Pneu.Frnt_Detector;
     else                     status = &Inst_Status.Pneu.Back_Detector;

     switch ( gas )
     {
          case 1:  status->Gas_1.On_Off = OFF;
                   break;
          case 2:  status->Gas_2.On_Off = OFF;
                   break;
          case 3:  status->Gas_3.On_Off = OFF;
                   break;
     }

}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

void DetGasON ( POSITION position, U_INT8 gas )

/**end_proto**/
{

     pDETECTOR_STATUS status;

     if ( position == FRONT ) status = &Inst_Status.Pneu.Frnt_Detector;
     else                     status = &Inst_Status.Pneu.Back_Detector;

     switch ( gas )
     {
       case 1: status->Gas_1.On_Off = status->Wkfile->Gas_1.On_Off;
               break;
       case 2: status->Gas_2.On_Off = status->Wkfile->Gas_2.On_Off;
               break;
       case 3: status->Gas_3.On_Off = status->Wkfile->Gas_3.On_Off;
               break;
     }
}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

void SetDetDutyCycle( POSITION position, U_INT8 gas, U_INT8 duty_cycle )

/**end_proto**/
{

   /* duty cycle is the number of counts (per 100) the valve in on */

     pDETECTOR_STATUS status;

     if ( position == FRONT ) status = &Inst_Status.Pneu.Frnt_Detector;
     else                     status = &Inst_Status.Pneu.Back_Detector;

     status->Duty_Cycle = duty_cycle;
     status->Modulated_Gas = gas;

}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

void SetDetGasIgnitionFlow( POSITION position, U_INT8 gas, U_INT32 flow )

/**end_proto**/
{

   /* flow is in integer ml/min  (unscaled) */

     pDETECTOR_STATUS status;

     if ( position == FRONT ) status = &Inst_Status.Pneu.Frnt_Detector;
     else                     status = &Inst_Status.Pneu.Back_Detector;


     switch ( gas )
     {
          case 1: status->Gas_1.Desired_Flow = flow * status->IU_Scaling;
                  break;
          case 2: status->Gas_2.Desired_Flow = flow * status->IU_Scaling;
                  break;
          case 3: status->Gas_3.Desired_Flow = flow * status->IU_Scaling;
                  break;
     }

}


/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

void StartDetIgnitionSeq( POSITION position )

/**end_proto**/
{

     pDETECTOR_STATUS status;

     if ( position == FRONT ) status = &Inst_Status.Pneu.Frnt_Detector;
     else                     status = &Inst_Status.Pneu.Back_Detector;

     status->In_Ignition_Sequence = TRUE;

    status->Ready.Setpt_Change = TRUE;
}



/**begin_proto**/

void EndDetIgnitionSeq( POSITION position )

/**end_proto**/
{

     pDETECTOR_STATUS status;

     if ( position == FRONT ) status = &Inst_Status.Pneu.Frnt_Detector;
     else                     status = &Inst_Status.Pneu.Back_Detector;

     if ( EpcDetector( status ) )
     {
         status->Gas_1.Desired_Flow = status->Wkfile->Gas_1.Desired_Flow;
         status->Gas_2.Desired_Flow = status->Wkfile->Gas_2.Desired_Flow;
         status->Gas_3.Desired_Flow = status->Wkfile->Gas_3.Desired_Flow;
     }

     status->In_Ignition_Sequence = FALSE;

     status->Duty_Cycle = 0;

    status->Ready.Setpt_Change = TRUE;
}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

GAS_TYPE DetGasType( POSITION p )

/**end_proto**/
{

     pDETECTOR_STATUS status;

     if ( p == FRONT ) status = &Inst_Status.Pneu.Frnt_Detector;
     else              status = &Inst_Status.Pneu.Back_Detector;

     if ( status->Wkfile->Gas_3.On_Off == ON )
     {
           return status->Config->Gas_3.Gas_Type;
     }
     else if (( Inst_Config.Pneu.Column_1.Outlet == status->Position ) &&
              ( Inst_Config.Pneu.Column_2.Outlet != status->Position ))
     {
           return GetColumnGasType( &Inst_Status.Pneu.Column_1 );
     }
     else if (( Inst_Config.Pneu.Column_1.Outlet != status->Position ) &&
              ( Inst_Config.Pneu.Column_2.Outlet == status->Position ))
     {
           return GetColumnGasType( &Inst_Status.Pneu.Column_2 );
     }
     else if (( Inst_Config.Pneu.Column_1.Outlet == status->Position ) &&
              ( Inst_Config.Pneu.Column_2.Outlet == status->Position ))
     {
           if ( status->Position == FRNT_DET )
           {
                return GetColumnGasType( &Inst_Status.Pneu.Column_1 );
           }
           else
           {
                return GetColumnGasType( &Inst_Status.Pneu.Column_2 );
           }
     }
     else
     {
           return UNKNOWN_GAS;
     }
}


/**begin_proto**/
#pragma SECTION PROG=rom3
/**end_proto**/

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

INT32 DcGetDetCalFlowGain ( pDETECTOR_STATUS status, U_INT8 gas_num )

/**end_proto**/
{
    U_INT16 gain;

    switch ( gas_num )
    {
       case 1: gain = status->Gas_1.Calib.Gain;
               break;
       case 2: gain = status->Gas_2.Calib.Gain;
               break;
       case 3: gain = status->Gas_3.Calib.Gain;
               break;
       default: gain = 0;
    }

    if ( GetDetGasStatus( status, gas_num ) == PRES ) return 0 ;

    return SignedQuadWordMultiplyDivide( CALIB_GAIN_DC_SCALE,
                                         gain - CALIB_GAIN_SCALING,
                                         CALIB_GAIN_SCALING );
}

/**begin_proto**/

INT32 DcGetDetCalPresGain ( pDETECTOR_STATUS status, U_INT8 gas_num )

/**end_proto**/
{
    U_INT16 gain;

    switch ( gas_num )
    {
       case 1: gain = status->Gas_1.Calib.Gain;
               break;
       case 2: gain = status->Gas_2.Calib.Gain;
               break;
       case 3: gain = status->Gas_3.Calib.Gain;
               break;
       default: gain = 0;
    }

    return SignedQuadWordMultiplyDivide( CALIB_GAIN_DC_SCALE,
                                         gain - CALIB_GAIN_SCALING,
                                         CALIB_GAIN_SCALING );
}

/**begin_proto**/

INT32 GetDetCalFlowZero ( pDETECTOR_STATUS status, U_INT8 gas_num )

/**end_proto**/
{

    pDET_GAS gas_table;
    U_INT16 atm_pres;
    U_INT16 temp;
    INT32 offset;

    temp   =  status->Tcomp_Tables->Thermistor.Module_Temperature;

    switch ( gas_num )
    {
       case 1: offset = status->Gas_1.Calib.Offset;
               gas_table = &status->Gas_1;
               break;
       case 2: offset = status->Gas_2.Calib.Offset;
               gas_table = &status->Gas_2;
               break;
       default:
       case 3: offset = status->Gas_3.Calib.Offset;
               gas_table = &status->Gas_3;
               break;
    }

    atm_pres = GetAmbientPressure( gas_table->Dcm2_Per_IU );

    return GetFritOffsetDispUnits ( offset, temp, atm_pres, gas_table );
}

/**begin_proto**/

INT32 DcGetDetCalFlowZero ( pDETECTOR_STATUS status, U_INT8 gas_num )

/**end_proto**/
{

    pDET_GAS gas_table;
    U_INT16 atm_pres;
    U_INT16 temp;
    INT32 offset;

    if ( GetDetGasStatus( status, gas_num ) == PRES ) return 0 ;

    temp   =  status->Tcomp_Tables->Thermistor.Module_Temperature;

    switch ( gas_num )
    {
       case 1: offset = status->Gas_1.Calib.Offset;
               gas_table = &status->Gas_1;
               break;
       case 2: offset = status->Gas_2.Calib.Offset;
               gas_table = &status->Gas_2;
               break;
       default:
       case 3: offset = status->Gas_3.Calib.Offset;
               gas_table = &status->Gas_3;
               break;
    }

    atm_pres = GetAmbientPressure( gas_table->Dcm2_Per_IU );

    return GetFritOffsetDcUnits ( offset, temp, atm_pres, gas_table );
}

/**begin_proto**/

INT32 GetDetCalFlow ( pDETECTOR_STATUS status, U_INT8 gas_num )

/**end_proto**/
{

   INT32 flow;

   switch ( gas_num )
   {
       case 1: flow = status->Gas_1.Calib.Flow;
               break;
       case 2: flow = status->Gas_2.Calib.Flow;
               break;
       default:
       case 3: flow = status->Gas_3.Calib.Flow;
               break;
   }

   return flow;  /* saved in display units */
}

/* ======================================================================================== */

/**begin_proto**/

INT32 DcGetDetCalPresValue( pDETECTOR_STATUS status, U_INT8 gas_num )

/**end_proto**/
{
   INT32   pres;
   U_INT16 dcm2;

   switch ( gas_num )
   {
       case 1: pres = status->Gas_1.Calib.CalPres;
               dcm2 = status->Gas_1.Dcm2_Per_IU;
               break;
       case 2: pres = status->Gas_2.Calib.CalPres;
               dcm2 = status->Gas_2.Dcm2_Per_IU;
               break;
       default:
       case 3: pres = status->Gas_3.Calib.CalPres;
               dcm2 = status->Gas_3.Dcm2_Per_IU;
               break;
   }
   return ConvertPresIuToDcu ( pres, dcm2 );

}


/**begin_proto**/

INT32 GetDetCalPresValue( pDETECTOR_STATUS status, U_INT8 gas_num )

/**end_proto**/
{
   INT32 pres;
   U_INT16 dcm2;

   switch ( gas_num )
   {
       case 1: pres = status->Gas_1.Calib.CalPres;
               dcm2 = status->Gas_1.Dcm2_Per_IU;
               break;
       case 2: pres = status->Gas_2.Calib.CalPres;
               dcm2 = status->Gas_2.Dcm2_Per_IU;
               break;
       default:
       case 3: pres = status->Gas_3.Calib.CalPres;
               dcm2 = status->Gas_3.Dcm2_Per_IU;
               break;
   }

   return ConvertPresIuToDisplay ( pres, dcm2 );
}

/**begin_proto**/

INT32 GetDetMinPresReqdToCalib( pDETECTOR_STATUS status, U_INT8 gas_num )

/**end_proto**/
{
   pPRES_SENSOR_STRUCT sensor;
   U_INT16 dcm2;

   switch ( gas_num )
   {
      default:
      case 1: sensor = &status->Gas_1.Tcomp_Tables->Pres_Sensor ;
              dcm2 = status->Gas_1.Dcm2_Per_IU;
              break;
      case 2: sensor = &status->Gas_1.Tcomp_Tables->Pres_Sensor ;
              dcm2 = status->Gas_2.Dcm2_Per_IU;
              break;
      case 3: sensor = &status->Gas_1.Tcomp_Tables->Pres_Sensor ;
              dcm2 = status->Gas_3.Dcm2_Per_IU;
              break;
   }

   return ConvertPresIuToDisplay ( GetPresRequiredToCalibrate( sensor ), dcm2 );
}

/**begin_proto**/

INT32 GetDetMaxPres( pDETECTOR_STATUS status, U_INT8 gas_num )

/**end_proto**/
{
    pDET_GAS            gas_table;

    switch ( gas_num )
    {
       default:
       case 1: gas_table = &status->Gas_1; break;
       case 2: gas_table = &status->Gas_2; break;
       case 3: gas_table = &status->Gas_3; break;
    }

    return ConvertPresIuToDisplay ( gas_table->P_Sensor_Range, gas_table->Dcm2_Per_IU );

}



/**begin_proto**/

INT32 GetDetCalPresZero ( pDETECTOR_STATUS status, U_INT8 gas_num )

/**end_proto**/
{
    pDET_GAS            gas_table;
    U_INT16 temp;

    switch ( gas_num )
    {
       default:
       case 1: gas_table = &status->Gas_1; break;
       case 2: gas_table = &status->Gas_2; break;
       case 3: gas_table = &status->Gas_3; break;
    }

    temp = status->Tcomp_Tables->Thermistor.Module_Temperature;

    return GetPresOffsetDispUnits ( gas_table->Calib.Offset, gas_table->Dcm2_Per_IU,
                                    &gas_table->Tcomp_Tables->Pres_Sensor, temp );

}

/**begin_proto**/

INT32 DcGetDetCalPresZero ( pDETECTOR_STATUS status, U_INT8 gas_num )

/**end_proto**/
{
    pDET_GAS            gas_table;
    U_INT16 temp;

    switch ( gas_num )
    {
       default:
       case 1: gas_table = &status->Gas_1; break;
       case 2: gas_table = &status->Gas_2; break;
       case 3: gas_table = &status->Gas_3; break;
    }

    temp = status->Tcomp_Tables->Thermistor.Module_Temperature;

    return GetPresOffsetDcUnits ( gas_table->Calib.Offset, gas_table->Dcm2_Per_IU,
                                    &gas_table->Tcomp_Tables->Pres_Sensor, temp );

}

/**begin_proto**/

UI_ERR SetDetCalPresZero ( pDETECTOR_STATUS status, U_INT8 gas_num  )

/**end_proto**/
{
   UI_ERR error;

   LockResource( &Inst_Status.Pneu.Resource_Lock );

   error = ChangeDetCalPresZero ( status, gas_num );

   ReleaseResource( &Inst_Status.Pneu.Resource_Lock );

   return error;
}

/**begin_proto**/

UI_ERR DcSetDetCalPresZero ( pDETECTOR_STATUS status, U_INT8 gas_num  )

/**end_proto**/
{
   UI_ERR error;

   error = ChangeDetCalPresZero ( status , gas_num );

   return error;
}

/**begin_proto**/

UI_ERR ChangeDetCalPresZero ( pDETECTOR_STATUS status, U_INT8 gas_num  )

/**end_proto**/
{
    U_INT16   temp;
    INT16     offset;
    UI_ERR    error;
    pDET_GAS  gas_table;
    BIT8      *SetptChgPtr;

    switch ( gas_num )
    {
       default:
       case 1: gas_table = &status->Gas_1;
               SetptChgPtr = &status->Ready.Fuel_Setpt_Change; break;

       case 2: gas_table = &status->Gas_2;
               SetptChgPtr = &status->Ready.Util_Setpt_Change; break;

       case 3: gas_table = &status->Gas_3;
               SetptChgPtr = &status->Ready.Mug_Setpt_Change; break;
    }

    temp = status->Tcomp_Tables->Thermistor.Module_Temperature;

    offset = CalcPresCalibOffset ( gas_table->Adc_Actual,
                                   &gas_table->Tcomp_Tables->Pres_Sensor,
                                   temp );
    if ((error = ValidatePresOffset( offset, gas_table->Dcm2_Per_IU,
                                     &gas_table->Tcomp_Tables->Pres_Sensor,
                                     temp )) != OK ) return error;

    if (OK != (error = ValidatePresOffset( offset,
                                           gas_table->Dcm2_Per_IU,
                                           &gas_table->Tcomp_Tables->Pres_Sensor,
                                           temp )                                 )     ) return error;

    gas_table->Calib.Offset = offset;

    SendDetCalibRequest ( status );

    LogSetptChange( status->Position == FRNT_DET ? F_DET_PRES_CALIB_ZERO : B_DET_PRES_CALIB_ZERO ,
                                                                               gas_num,0  );
    *SetptChgPtr = TRUE ;

    return OK;
}

/**begin_proto**/

UI_ERR SetDetCalPres ( pDETECTOR_STATUS status, U_INT8 gas_num, INT32 pres )

/**end_proto**/
{
      UI_ERR  error;
      U_INT32 pres_iu;
      pDET_GAS            gas_table;

      switch ( gas_num )
      {
         default:
         case 1: gas_table = &status->Gas_1; break;
         case 2: gas_table = &status->Gas_2; break;
         case 3: gas_table = &status->Gas_3; break;
      }


      if ( pres <= 0 ) return PARAM_TOO_SMALL;
      if ( pres > GetDetMaxPres(status,gas_num) ) return PARAM_TOO_LARGE;

      if ( gas_table->Current_Pres == 0 ) return NOT_ALLOWED;

      pres_iu = ConvertPresDisplayToIu( pres, gas_table->Dcm2_Per_IU );

      LockResource( &Inst_Status.Pneu.Resource_Lock );

      error = ChangeDetCalPres( status, gas_table, gas_num, pres, pres_iu );

      ReleaseResource( &Inst_Status.Pneu.Resource_Lock );

      return error;
}

/**begin_proto**/

UI_ERR DcSetDetCalPres ( pDETECTOR_STATUS status, U_INT8 gas_num, INT32 pres )

/**end_proto**/
{

      INT32   pres_dispu;
      U_INT32 pres_iu;
      pDET_GAS            gas_table;

      switch ( gas_num )
      {
         default:
         case 1: gas_table = &status->Gas_1; break;
         case 2: gas_table = &status->Gas_2; break;
         case 3: gas_table = &status->Gas_3; break;
      }


      pres_iu = ConvertPresDcuToIu ( pres, gas_table->Dcm2_Per_IU );
      pres_dispu = ConvertPresIuToDisplay( pres_iu, gas_table->Dcm2_Per_IU );

      if ( pres <= 0 ) return PARAM_TOO_SMALL;
      if ( pres > ConvertPresIuToDcu(gas_table->P_Sensor_Range, gas_table->Dcm2_Per_IU) ) return PARAM_TOO_LARGE;
      if ( gas_table->Current_Pres == 0 ) return NOT_ALLOWED;

      return  ChangeDetCalPres( status, gas_table, gas_num, pres_dispu, pres_iu );

}

/**begin_proto**/

UI_ERR ChangeDetCalPres ( pDETECTOR_STATUS status, pDET_GAS gas_table, U_INT8 chnl, INT32 pres, U_INT32 pres_iu )

/**end_proto**/
{

    UI_ERR  error;
    U_INT16 gain;

    if (!EnoughPresToCalibrate( gas_table->Current_Pres,
                                &gas_table->Tcomp_Tables->Pres_Sensor,
                                gas_table->Dcm2_Per_IU )) return OUTSIDE_ALLOWED_RANGE;

    gain = CalcCalibGain ( gas_table->Current_Pres, pres_iu, gas_table->Calib.Gain );

    if ((error=ValidatePresCalibGain(gain))!= OK ) return error;

    gas_table->Calib.Gain =  gain;
    gas_table->Calib.CalPres = pres_iu;

    SendDetCalibRequest ( status );

    LogSetptChange( status->Position == FRNT_DET ? F_DET_PRES_CALIB : B_DET_PRES_CALIB, pres, chnl );
    switch ( chnl    )
    {
       default:
       case 1: status->Ready.Fuel_Setpt_Change = TRUE; break;
       case 2: status->Ready.Util_Setpt_Change = TRUE; break;
       case 3: status->Ready.Mug_Setpt_Change  = TRUE; break;
    }
    return OK;
}

/* ======================================================================================== */

/**begin_proto**/

INT32 DcGetDetCalFlow ( pDETECTOR_STATUS status, U_INT8 gas_num )

/**end_proto**/
{

   INT32 flow;

    if ( GetDetGasStatus( status, gas_num ) == PRES ) return 0 ;

   switch ( gas_num )
   {
       case 1: flow = status->Gas_1.Calib.Flow;
               break;
       case 2: flow = status->Gas_2.Calib.Flow;
               break;
       default:
       case 3: flow = status->Gas_3.Calib.Flow;
               break;
   }
      /* flow is saved in display units */

      flow = ConvertFlowDisplayToIu( flow, status->IU_Scaling );
      return ConvertFlowIuToDcu ( flow, status->IU_Scaling );
}

/**begin_proto**/

UI_ERR SetDetCalFlowZero ( pDETECTOR_STATUS status, U_INT8 gas_num )

/**end_proto**/
{
    UI_ERR error;

    LockResource ( &Inst_Status.Pneu.Resource_Lock );

    error = ChangeDetCalFlowZero ( status, gas_num );

    ReleaseResource ( &Inst_Status.Pneu.Resource_Lock );

    return error;
}

/**begin_proto**/

UI_ERR DcSetDetCalFlowZero ( pDETECTOR_STATUS status, U_INT8 gas_num )

/**end_proto**/
{
    UI_ERR error;

    error = ChangeDetCalFlowZero ( status, gas_num );

    return error;
}


/**begin_proto**/

UI_ERR ChangeDetCalFlowZero ( pDETECTOR_STATUS status, U_INT8 gas_num )

/**end_proto**/
{
   UI_ERR  error;
   INT32   offset;
   U_INT16 temp;
   U_INT16 atm_pres;

   temp = status->Tcomp_Tables->Thermistor.Module_Temperature;

   switch ( gas_num )
   {
       case 1: offset = CalcFritCalibOffset ( status->Gas_1.Adc_Actual, &status->Gas_1, temp );
               atm_pres = GetAmbientPressure( status->Gas_1.Dcm2_Per_IU );
               if (( error = ValidateFritOffset( offset, temp, atm_pres, &status->Gas_1 ) ) != OK ) return error;
               break;

       case 2: offset = CalcFritCalibOffset ( status->Gas_2.Adc_Actual, &status->Gas_2, temp );
               atm_pres = GetAmbientPressure( status->Gas_2.Dcm2_Per_IU );
               if (( error = ValidateFritOffset( offset, temp, atm_pres, &status->Gas_2 ) ) != OK ) return error;
               break;

       default:
       case 3: offset = CalcFritCalibOffset ( status->Gas_3.Adc_Actual, &status->Gas_3, temp );
               atm_pres = GetAmbientPressure( status->Gas_3.Dcm2_Per_IU );
               if (( error = ValidateFritOffset( offset, temp, atm_pres, &status->Gas_3 ) ) != OK ) return error;
               break;

   }


   switch ( gas_num )
   {
       case 1: status->Gas_1.Calib.Offset = offset;
               LogSetptChange( status->Position == FRNT_DET ? F_DET_FUEL_CALIB_ZERO :
                                                              B_DET_FUEL_CALIB_ZERO,   0, 0 );
               status->Ready.Fuel_Setpt_Change = TRUE;
               break;

       case 2: status->Gas_2.Calib.Offset = offset;
               LogSetptChange( status->Position == FRNT_DET ? F_DET_UTIL_CALIB_ZERO :
                                                              B_DET_UTIL_CALIB_ZERO,   0, (INT32)status->Config->Type );
               status->Ready.Util_Setpt_Change = TRUE;
               break;

       case 3: status->Gas_3.Calib.Offset = offset;
               LogSetptChange( status->Position == FRNT_DET ? F_DET_MUG_CALIB_ZERO :
                                                              B_DET_MUG_CALIB_ZERO,    0, 0 );
               status->Ready.Mug_Setpt_Change = TRUE;
               break;
   }

   SendDetCalibRequest ( status );

   return OK;
}

/**begin_proto**/

UI_ERR DcSetDetFactoryCalFlowZero ( pDETECTOR_STATUS status )

/**end_proto**/
{
   UI_ERR  error1, error2, error3;
   INT32   offset1, offset2, offset3;
   U_INT16 temp;
   U_INT16 atm_pres;

   if ( !EpcDetector ( status ) ) return NOT_ALLOWED;

   temp = status->Tcomp_Tables->Thermistor.Module_Temperature;

   if (!DetIsTCDorAnyECD( status ) )
   {
       offset1 = CalcFritCalibOffset ( status->Gas_1.Adc_Actual, &status->Gas_1, temp );
       atm_pres = GetAmbientPressure( status->Gas_1.Dcm2_Per_IU );
       error1 = ValidateFritOffset( offset1, temp, atm_pres, &status->Gas_1 );
   }
   else
   {
        offset1 = 0;
        error1  = OK;
   }

   offset2 = CalcFritCalibOffset ( status->Gas_2.Adc_Actual, &status->Gas_2, temp );
   atm_pres = GetAmbientPressure( status->Gas_2.Dcm2_Per_IU );
   error2 = ValidateFritOffset( offset2, temp, atm_pres, &status->Gas_2 );


   offset3 = CalcFritCalibOffset ( status->Gas_3.Adc_Actual, &status->Gas_3, temp );
   atm_pres = GetAmbientPressure( status->Gas_3.Dcm2_Per_IU );
   error3 = ValidateFritOffset( offset3, temp, atm_pres, &status->Gas_3 );

   if (( error1 == OK ) && ( error2 == OK ) && ( error3 == OK ))
   {
       if (!DetIsTCDorAnyECD( status ) )
       {
            status->Gas_1.Calib.Offset = offset1;
            LogSetptChange( status->Position == FRNT_DET ? F_DET_FUEL_CALIB_ZERO :
                                                           B_DET_FUEL_CALIB_ZERO,   0, 0 );
            status->Ready.Fuel_Setpt_Change = TRUE;
       }

       if (!DetIsAnyUECD( status ) )
       {
            status->Gas_2.Calib.Offset = offset2;
            LogSetptChange( status->Position == FRNT_DET ? F_DET_UTIL_CALIB_ZERO :
                                                           B_DET_UTIL_CALIB_ZERO,   0, (INT32)status->Config->Type );
       }

       status->Ready.Util_Setpt_Change = TRUE;

       status->Gas_3.Calib.Offset = offset3;
       LogSetptChange( status->Position == FRNT_DET ? F_DET_MUG_CALIB_ZERO :
                                                      B_DET_MUG_CALIB_ZERO,    0, 0 );
       status->Ready.Mug_Setpt_Change = TRUE;

       status->Gas_1.Calib.Gain  = CALIB_GAIN_SCALING;
       status->Gas_1.Calib.Flow  = 0;
       status->Gas_2.Calib.Gain  = CALIB_GAIN_SCALING;
       status->Gas_2.Calib.Flow  = 0;
       status->Gas_3.Calib.Gain  = CALIB_GAIN_SCALING;
       status->Gas_3.Calib.Flow  = 0;
       InitializeDateTime( &status->Calib_Date );

       SaveDetFactoryCalib( status );
       return OK;
   }
   else
   {
       return TEST_FAILED;
   }
}

/**begin_proto**/

UI_ERR SetDetCalFlow ( pDETECTOR_STATUS status, U_INT8 gas_num, INT32 flow )

/**end_proto**/
{

      U_INT32 flow_iu;
      UI_ERR  error;

      if ( flow <= 0 ) return PARAM_TOO_SMALL;
      if ( flow > GetMaxDetGasFlow( status, gas_num ) ) return PARAM_TOO_LARGE;

      flow_iu = ConvertFlowDisplayToIu( flow, status->IU_Scaling );

      LockResource( &Inst_Status.Pneu.Resource_Lock );

      error = ChangeDetCalFlow ( status, gas_num, flow, flow_iu );

      ReleaseResource( &Inst_Status.Pneu.Resource_Lock );

      return error;
}

/**begin_proto**/

UI_ERR DcSetDetCalFlow ( pDETECTOR_STATUS status, U_INT8 gas_num, INT32 flow )

/**end_proto**/
{

      U_INT32 flow_iu;

      if ( flow == 0 ) return INVALID_PARAM;

      flow_iu = ConvertFlowDcuToIu    ( flow,    status->IU_Scaling );

       /* remember flow is saved in display units */
      flow    = ConvertFlowIuToDisplay( flow_iu, status->IU_Scaling );

      return ChangeDetCalFlow ( status, gas_num, flow, flow_iu );

}

/**begin_proto**/

UI_ERR ChangeDetCalFlow ( pDETECTOR_STATUS status, U_INT8 gas_num, INT32 flow, U_INT32 flow_iu )

/**end_proto**/
{

     U_INT16 gain;

       /* remember flow is saved in display units */

      switch ( gas_num )
      {
          case 1: if (!EnoughFritFlowToCalibrate( status->Gas_1.Filtered_Current_Flow,
                                                  &status->Tcomp_Tables->Fuel.Frit,
                                                  status->Gas_1.IU_Scaling )) return OUTSIDE_ALLOWED_RANGE;

                  gain = CalcCalibGain ( status->Gas_1.Filtered_Current_Flow, flow_iu, status->Gas_1.Calib.Gain );

                  if ( ValidateFritCalibGain(gain) != OK ) return EXCEEDS_CALIB_RANGE;

                  status->Gas_1.Calib.Gain = gain;
                  status->Gas_1.Calib.Flow = flow;
                  LogSetptChange( status->Position == FRNT_DET ? F_DET_FUEL_CALIB_FLOW : B_DET_FUEL_CALIB_FLOW,
                               flow, 0 );
                  status->Ready.Fuel_Setpt_Change = TRUE;
                  break;

          case 2: if (!EnoughFritFlowToCalibrate( status->Gas_2.Filtered_Current_Flow,
                                                  &status->Tcomp_Tables->Util.Frit,
                                                  status->Gas_2.IU_Scaling )) return OUTSIDE_ALLOWED_RANGE;

                  gain = CalcCalibGain ( status->Gas_2.Filtered_Current_Flow, flow_iu, status->Gas_2.Calib.Gain );

                  if ( ValidateFritCalibGain(gain) != OK ) return EXCEEDS_CALIB_RANGE;

                  status->Gas_2.Calib.Gain = gain;
                  status->Gas_2.Calib.Flow = flow;
                  LogSetptChange( status->Position == FRNT_DET ? F_DET_UTIL_CALIB_FLOW : B_DET_UTIL_CALIB_FLOW,
                               flow, (INT32)status->Config->Type );
                  status->Ready.Util_Setpt_Change = TRUE;
                  break;

          case 3: if (!EnoughFritFlowToCalibrate( status->Gas_3.Filtered_Current_Flow,
                                                  &status->Tcomp_Tables->Mug.Frit,
                                                  status->Gas_3.IU_Scaling )) return OUTSIDE_ALLOWED_RANGE;

                  gain = CalcCalibGain ( status->Gas_3.Filtered_Current_Flow, flow_iu, status->Gas_3.Calib.Gain );

                  if ( ValidateFritCalibGain(gain) != OK ) return EXCEEDS_CALIB_RANGE;

                  status->Gas_3.Calib.Gain = gain;
                  status->Gas_3.Calib.Flow = flow;
                  LogSetptChange( status->Position == FRNT_DET ? F_DET_MUG_CALIB_FLOW : B_DET_MUG_CALIB_FLOW,
                               flow, 0 );
                  status->Ready.Mug_Setpt_Change = TRUE;
                  break;
      }

      SendDetCalibRequest ( status );

      return OK;
}

/**begin_proto**/

INT32 GetMinFritFlowReqdToCalib ( pDETECTOR_STATUS status, U_INT8 gas_num )

/**end_proto**/
{
      pFRIT_STRUCT frit;

      switch ( gas_num )
      {
          case 1: frit = &status->Tcomp_Tables->Fuel.Frit;
                  break;
          case 2: frit = &status->Tcomp_Tables->Util.Frit;
                  break;
          case 3: frit = &status->Tcomp_Tables->Mug.Frit;
                  break;

          default: return 0;
      }

      return ConvertFlowIuToDisplay( GetFritFlowRequiredToCalibrate( frit ), status->IU_Scaling );

}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

DATETIME GetDetCalibDate( pDETECTOR_STATUS status )

/**end_proto**/
{

     return status->Calib_Date;

}


/**begin_proto**/

UI_ERR ValidateDetCalibState( pDETECTOR_STATUS status, ON_OFF  state )

/**end_proto**/
{

/* there is a failure posible here, if multiple cmds to enable or */
/* disable calib are stacked in the gastask queue, this routine   */
/* can give false results.                                        */

    UI_ERR error;

    if ( EpcDetector( status ) )
    {
        if (( state == OFF ) && ( DetUserCalibState( status ) == USER_ENABLED ))
        {
            error = OK;
        }
        else if (( state == ON ) && ( DetUserCalibState( status ) == USER_DISABLED ))
        {
            error = OK;
        }
        else
        {
            error = INVALID_OP;
        }
    }
    else
    {
        error = NOT_ALLOWED;
    }

    return error;

}

/**begin_proto**/

UI_ERR TurnOffDetCalib( pDETECTOR_STATUS status )

/**end_proto**/
{
    UI_ERR error;

    if ( (error =  ValidateDetCalibState( status, OFF )) == OK )
    {
        LockResource( &Inst_Status.Pneu.Resource_Lock );

        SendDetDisableUserRequest( status );

        ReleaseResource( &Inst_Status.Pneu.Resource_Lock );
    }

    return error;
}

/**begin_proto**/

UI_ERR DcTurnOffDetCalib( pDETECTOR_STATUS status )

/**end_proto**/
{
    UI_ERR error;

    if ( (error =  ValidateDetCalibState( status, OFF )) == OK )
    {
        SendDetDisableUserRequest( status );
    }

    return error;
}


/**begin_proto**/

UI_ERR TurnOnDetCalib( pDETECTOR_STATUS status )

/**end_proto**/
{
    UI_ERR error;

    if ( (error =  ValidateDetCalibState( status, ON )) == OK )
    {
        LockResource( &Inst_Status.Pneu.Resource_Lock );

        SendDetEnableUserRequest( status );

        ReleaseResource( &Inst_Status.Pneu.Resource_Lock );
    }

    return error;
}

/**begin_proto**/

UI_ERR DcTurnOnDetCalib( pDETECTOR_STATUS status )

/**end_proto**/
{
    UI_ERR error;

    if ( (error =  ValidateDetCalibState( status, ON )) == OK )
    {
        SendDetEnableUserRequest( status );
    }

    return error;
}


/**begin_proto**/

UI_ERR ChangeDetCalibState( pDETECTOR_STATUS status, ON_OFF  state )

/**end_proto**/
{
    UI_ERR error;

    if ( EpcDetector( status ) )
    {
        if (( state == OFF ) && ( DetUserCalibState( status ) == USER_ENABLED ))
        {
            DisableDetCalib ( status );
            LogSetptChange( status->Position == FRNT_DET ? F_DET_CAL_DISABLED : B_DET_CAL_DISABLED, 0, 0 );
            error = OK;
        }
        else if (( state == ON ) && ( DetUserCalibState( status ) == USER_DISABLED ))
        {
            EnableDetCalib( status );
            LogSetptChange( status->Position == FRNT_DET ? F_DET_CAL_ENABLED : B_DET_CAL_ENABLED, 0, 0 );
            error = OK;
        }
        else
        {
            error = INVALID_OP;
        }
    }
    else
    {
        error = NOT_ALLOWED;
    }

    return error;

}

/**begin_proto**/

UI_ERR DeleteDetCalib ( pDETECTOR_STATUS status )

/**end_proto**/
{
    UI_ERR error;

    LockResource( &Inst_Status.Pneu.Resource_Lock );

    error = SendDeleteDetCalib( status );

    ReleaseResource( &Inst_Status.Pneu.Resource_Lock );

    return error;
}

/**begin_proto**/

UI_ERR DcDeleteDetCalib ( pDETECTOR_STATUS status )

/**end_proto**/
{
    UI_ERR error;

    error = SendDeleteDetCalib( status );

    return error;
}

/**begin_proto**/

UI_ERR SendDeleteDetCalib ( pDETECTOR_STATUS status )

/**end_proto**/
{
    if ( !EpcDetector( status ) ) return NOT_ALLOWED;
    if ( DetUserCalibState( status ) == FACTORY ) return INVALID_OP;

    SendDetScratchRequest ( status );

    LogSetptChange( status->Position == FRNT_DET ? F_DET_CALIB_DELETED : B_DET_CALIB_DELETED, 0, 0 );
    status->Ready.Setpt_Change = TRUE;

    return OK;
}

/**begin_proto**/

CALIB_STATE DetUserCalibState ( pDETECTOR_STATUS status )

/**end_proto**/
{
    return status->Calib_State;
}



/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

BIT8 EpcDetector( pDETECTOR_STATUS  status )

/**end_proto**/
{
    if ( !status->Config->Functional ) return FALSE; /* dead det */

    return  ( (U_INT16)status->Config->Type & EPC_DET_BIT ) != 0;
}
/**begin_proto**/

BIT8 DCEpcDetector( pDETECTOR_STATUS  status )

/**end_proto**/
{
    /* Used by DataComm to determine if EPC */
    /* Can't use EpcDetector() since if nonfunctional detector, */
    /*     still need to know if EPC - for OIM programming */

    return  ( (U_INT16)status->Config->Type & EPC_DET_BIT ) != 0;
}


/**begin_proto**/

BIT8 ManDetector( pDETECTOR_STATUS  status )

/**end_proto**/
{
    if ( !status->Config->Functional ) return FALSE; /* dead det */

    return  ( (U_INT16)status->Config->Type & EPC_DET_BIT ) == 0;
}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

BIT8 IsDetectorEpc( POSITION position )

/**end_proto**/
{

   return EpcDetector( ( position == FRONT ) ?
             &Inst_Status.Pneu.Frnt_Detector :
             &Inst_Status.Pneu.Back_Detector );


}

/**begin_proto**/

BIT8 DCIsDetectorEpc( POSITION position )

/**end_proto**/
{

   return DCEpcDetector( ( position == FRONT ) ?
             &Inst_Status.Pneu.Frnt_Detector :
             &Inst_Status.Pneu.Back_Detector );


}


/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

EEPROM_DET_TYPE GetDetType( pDETECTOR_STATUS status )

/**end_proto**/
{
   return status->Config->Type;
}


/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

INT32  DcGetDetFuelGasMaxFlowRate( pDETECTOR_STATUS status, GAS_TYPE gas_type )

/**end_proto**/
{
     return ConvertFlowIuToDcu ( status->Gas_1.Tcomp_Tables->Frit.Parms.Max_Gas_Flow_Rates[ (U_INT8) gas_type ],
                                 status->IU_Scaling );
}
/**begin_proto**/

INT32  DcGetDetUtilGasMaxFlowRate( pDETECTOR_STATUS status, GAS_TYPE gas_type )

/**end_proto**/
{
     return ConvertFlowIuToDcu ( status->Gas_2.Tcomp_Tables->Frit.Parms.Max_Gas_Flow_Rates[ (U_INT8) gas_type ],
                                 status->IU_Scaling );
}
/**begin_proto**/

INT32  DcGetDetMugGasMaxFlowRate( pDETECTOR_STATUS status, GAS_TYPE gas_type )

/**end_proto**/
{
     return ConvertFlowIuToDcu ( status->Gas_3.Tcomp_Tables->Frit.Parms.Max_Gas_Flow_Rates[ (U_INT8) gas_type ],
                                 status->IU_Scaling );
}

/**begin_proto**/

OEM_GAS_STATUS  GetDetGasStatus( pDETECTOR_STATUS status, BIT8 gas )

/**end_proto**/
{
   if ( 0 == GetDetMaxPres( status, gas ) )
   {
      return NOT_USED;
   }

   if ( 0 == GetMaxDetGasFlow( status, gas ) )
   {
      return PRES ;
   }
   else
   {
      return FLOW;
   }
}



/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

void RTTSetFrntDetFuelState( INT32 state )

/**end_proto**/
{

    Inst_Status.Pneu.Frnt_Detector.Gas_1.On_Off = (ON_OFF)( state != 0 );

}


/**begin_proto**/

void RTTSetBackDetFuelState( INT32 state )

/**end_proto**/
{

    Inst_Status.Pneu.Back_Detector.Gas_1.On_Off = (ON_OFF)( state != 0 );

}


/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

void RTTResetDetectorStates( void )

/**end_proto**/
{

    Inst_Status.Pneu.Frnt_Detector.Gas_1.On_Off = Active_Wkfile.Pneu.Frnt_Detector.Gas_1.On_Off;
    Inst_Status.Pneu.Frnt_Detector.Gas_2.On_Off = Active_Wkfile.Pneu.Frnt_Detector.Gas_2.On_Off;
    Inst_Status.Pneu.Frnt_Detector.Gas_3.On_Off = Active_Wkfile.Pneu.Frnt_Detector.Gas_3.On_Off;

    Inst_Status.Pneu.Back_Detector.Gas_1.On_Off = Active_Wkfile.Pneu.Back_Detector.Gas_1.On_Off;
    Inst_Status.Pneu.Back_Detector.Gas_2.On_Off = Active_Wkfile.Pneu.Back_Detector.Gas_2.On_Off;
    Inst_Status.Pneu.Back_Detector.Gas_3.On_Off = Active_Wkfile.Pneu.Back_Detector.Gas_3.On_Off;

}

/**begin_proto**/
#pragma SECTION UNDO
/**end_proto**/
